package com.sduept.nwld.dataserver.controller.fault;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.primefaces.PrimeFaces;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.DualListModel;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sduept.bigdata.document.core.CommonDocumentProperties;
import com.sduept.bigdata.fault.common.ParamDesc;
import com.sduept.bigdata.fault.entity.AnalLinefaultEtl;
import com.sduept.bigdata.fault.entity.FaultDetail;
import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.bigdata.fault.entity.FaultRecordAttachment;
import com.sduept.bigdata.fault.entity.FaultRecordWrapper;
import com.sduept.bigdata.fault.entity.FaultWaveFileRelation;
import com.sduept.bigdata.fault.enums.WaveFileTypeEnum;
import com.sduept.bigdata.fault.manager.FaultDetailManager;
import com.sduept.bigdata.fault.manager.FaultEditLockManager;
import com.sduept.bigdata.fault.manager.FaultExtendManager;
import com.sduept.bigdata.fault.manager.FaultForecastIdentifyManager;
import com.sduept.bigdata.fault.manager.FaultManager;
import com.sduept.bigdata.fault.manager.FaultRecordAttachmentManager;
import com.sduept.bigdata.fault.manager.FaultRecordExportManager;
import com.sduept.bigdata.fault.manager.FaultRecordPersistManager;
import com.sduept.bigdata.fault.manager.FaultRecordQueryManager;
import com.sduept.bigdata.fault.manager.FaultSourcePersistManager;
import com.sduept.bigdata.fault.manager.FaultWaveFileRelationManager;
import com.sduept.bigdata.fault.manager.ProcessItemConfigManager;
import com.sduept.bigdata.fault.manager.ResourcePermissFacde;
import com.sduept.bigdata.fault.model.AcLineInfoDTO;
import com.sduept.bigdata.fault.model.DisconnectorInfoDTO;
import com.sduept.bigdata.fault.model.FaultRecordDetailDTO;
import com.sduept.bigdata.fault.model.ProcessNodeDTO;
import com.sduept.bigdata.fault.special.maintenance.manager.MaintenancePersistManager;
import com.sduept.bigdata.fault.system.properties.FaultSystemProperties;
import com.sduept.bigdata.ml.domain.LibSvmData;
import com.sduept.bigdata.weather.faultcause.manager.FaultCauseManager;
import com.sduept.bigdata.weather.map.MapDataCache;
import com.sduept.cim.ledger.manager.EquipmentLedgerManager;
import com.sduept.cim.ledger.manager.LineSegmentLedgerManager;
import com.sduept.cim.ledger.manager.SubstationLedgerManager;
import com.sduept.cim.ledger.model.ManagementUnitDict;
import com.sduept.cim.ledger.model.PowerResourceLedger;
import com.sduept.cim.ledger.model.PrimaryEquipmentLedger;
import com.sduept.cim.ledger.model.SubstationLedger;
import com.sduept.cim.model.core.Equipment;
import com.sduept.cim.model.core.Substation;
import com.sduept.cim.model.extend.AbstractWaveFile;
import com.sduept.cim.model.extend.LineSegment;
import com.sduept.cim.model.extend.ProtectWaveFile;
import com.sduept.cim.model.extend.WaveFile;
import com.sduept.cim.model.generation.GeneratingUnit;
import com.sduept.cim.model.generation.HydroGeneratingUnit;
import com.sduept.cim.model.generation.ThermalGeneratingUnit;
import com.sduept.cim.model.history.extend.LineSegmentHistory;
import com.sduept.cim.model.history.wires.ACLineSegmentHistory;
import com.sduept.cim.model.history.wires.DcLinesegmentHistory;
import com.sduept.cim.model.protection.ProtectionEquipment;
import com.sduept.cim.model.protection.WaveEquipment;
import com.sduept.cim.model.wires.ACLineSegment;
import com.sduept.cim.model.wires.Breaker;
import com.sduept.cim.model.wires.BusbarSection;
import com.sduept.cim.model.wires.Compensator;
import com.sduept.cim.model.wires.DcLinesegment;
import com.sduept.cim.model.wires.PowerTransformer;
import com.sduept.core.ParamManager;
import com.sduept.core.dao.SuperDAO;
import com.sduept.core.entity.IdentifiedObject;
import com.sduept.core.entity.SystemParameter;
import com.sduept.generator.ObjectId;
import com.sduept.nwld.dataserver.controller.daily.DailyReportAbstractController;
import com.sduept.nwld.dataserver.controller.fault.excel.ImportOmsDTO;
import com.sduept.nwld.dataserver.controller.fault.excel.OmsExcelDataListener;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.dataserver.manager.fault.FaultSourceQueryManager;
import com.sduept.nwld.dataserver.model.lbtz.AnalyseLogDTO;
import com.sduept.nwld.fault.analysis.model.FaultUploadInfoDTO;
import com.sduept.permission.exception.AuthorizationException;
import com.sduept.permission.manager.PersonnelManager;
import com.sduept.utils.DateUtil;
import com.sduept.utils.PingYinUtil;

import lombok.extern.slf4j.Slf4j;
@Slf4j
@Named
@ViewScoped
/**
 * 线路故障controller类
 */
public class FaultReportController extends DailyReportAbstractController {
	private static final long serialVersionUID = 5233283549395529450L;
	/**
	 * 树节点类型
	 */
	public static final String TREE_TYPE_Container = Substation.class.getSimpleName();
	public static final String TREE_TYPE_Equipment = "Equipment";
	public static final String TREE_TYPE_Dir = "1";
	/**
	 * 文件上传和下载
	 */
	public static final String FILE_FORMAT_CFG = "cfg";
	public static final String FILE_FORMAT_DAT = "dat";
	private static final String POLE_REGEX_1 = "[^#]*#([0-9]+).*";
	private static final String POLE_REGEX_2 = "[^\\d]*([0-9]+)号塔.*";
	@Autowired
	private FaultManager bx;
	@Autowired
	private FaultExtendManager fem;
	@Autowired
	private FaultRecordPersistManager frm;
	@Autowired
	private FaultForecastIdentifyManager fim;
	@Autowired
	private  FaultCauseManager fcm;
	@Autowired
	private  FaultSystemProperties pros ;
	@Autowired
	private  CommonDocumentProperties webpros ;
	@Autowired
	private ResourcePermissFacde rpf;
	@Autowired
	private FaultRecordQueryManager fm;
	@Autowired
	private CimManager cim;
	@Autowired
	private MapDataCache cmc;
	@Autowired
	private SuperDAO dao;
	@Autowired
	private FaultSourcePersistManager sourceManager;
	@Autowired
	private SubstationLedgerManager stationLedgerM;
	@Autowired
	private FaultRecordExportManager exportm;
	@Autowired
	private LineSegmentLedgerManager lineLedgerM;
	@Autowired
	private EquipmentLedgerManager equipmentLedgerM;
	@Autowired
	private ParamManager cacheM;
	@Autowired
	private FaultEditLockManager lockM;
	@Autowired
	private PersonnelManager personM;
	@Autowired
	private ProcessItemConfigManager processM;
	@Autowired
	private FaultSourceQueryManager faultSourcesM;
	@Autowired
	private MaintenancePersistManager mpm;
	@Autowired
	private FaultRecordAttachmentManager attManager;
	@Autowired
	private FaultWaveFileRelationManager waveFileMamager;
	@Autowired
	private FaultDetailManager fdM;

	private final static String FAULTFREQUENTMAPKEY = "faultFrequentMap";
	/**
	 * 故障表格展示
	 */
	private LazyDataModel<FaultRecord> lineFaultsModel;// 表格懒加载模型
	private List<FaultRecord> lineFaults;// 表格数据
	private FaultRecord selected = null;// 当前选择的表格条目
	private FaultRecord selectEdit = null;
	private int count;
	private List<FaultRecord> selectFaults = null; // 表格选择数据
	private String predictResult = null;
	private   Map<String,List<String>> faultReasonMap = new HashMap<>();
	/**
	 * 文件下载
	 */
	private String tmpPath = "";
	private StreamedContent file;

	/**
	 * 查看日志弹窗列表
	 */
	private List<AnalyseLogDTO> analyseLogDTOs = new ArrayList<>();// 日志显示

	/**
	 * 故障查询条件
	 */
	private String isFault = "0"; // 是否故障查询
	private String selectedVoltage = "499";
	private String faultDevice = ""; // 故障设备名称
	private boolean hasRemark;
	private FaultRecord queryFault;

	/**
	 * 新建和编辑故障对话框
	 */
	private String OMSInfo = null;
	// 自动填充列表们
	private List<String> etypeList = new ArrayList<String>(); // 设备类型
	private List<String> voltageList = new ArrayList<String>(); // 电压等级
	private List<String> faultTypeList = new ArrayList<String>(); // 故障类型
	// 相别弹窗
	private String[] selectedPhase; // 选择的相别
	private boolean create; // 当新建时可以选择设备、编辑时不能更改选择设备。同时该属性也定义了当前是否为新建故障。
	private boolean showStation2; // 是否显示结束站
	private List<String> phases = new ArrayList<String>();// 故障相别列表
	private IdentifiedObject equipment; // 选择的设备
	private Date faultDate;
	private String hour = "00";
	private String minute = "00";
	private String second = "00";

	private PowerResourceLedger ledger;
	private String equipmentType;
	private String dispatchUnit;
	private List<FaultRecord> samefaults;// 表格数据
	/**
	 * 暂存当前选择记录的动作过程
	 */
	private String currentSelectRecordDesc;
	private boolean ifClick = false; // 判断故障过程文本框是否点击过，仅第一次点击有效
	private List<ProcessNodeDTO> processNodes = new ArrayList<ProcessNodeDTO>();
	private List<FaultUploadInfoDTO> sourceInfos = new ArrayList<>();
	List<String> acLineInfoList = new ArrayList<String>();
	private List<FaultRecord> frequentFaults = new ArrayList<>();
	private List<FaultRecord> selectFrequentFaults = new ArrayList<>();
	private Map<String, Object> frequentFaultsMap;
	/**
	 * 故障档案附件及录波文件合并功能
	 */
	private List<FaultRecordAttachment> attachmentStation1 = new ArrayList<FaultRecordAttachment>();//TODO
	private List<FaultRecordAttachment> attachmentStation2 = new ArrayList<FaultRecordAttachment>();
	private List<FaultRecordAttachment> attachments1 = new ArrayList<FaultRecordAttachment>();
	private List<FaultRecordAttachment> attachments2 = new ArrayList<FaultRecordAttachment>();
	private DualListModel<FaultRecordAttachment> attachmentsPickList = new DualListModel<FaultRecordAttachment>(attachmentStation1,attachments1) ;
	private DualListModel<FaultRecordAttachment> attachmentsPickList1 = new DualListModel<FaultRecordAttachment>(attachmentStation2,attachments2) ;

    private List<AbstractWaveFile> waveFileStation1= new ArrayList<AbstractWaveFile>();
    private List<AbstractWaveFile> waveFileStation2= new ArrayList<AbstractWaveFile>();
    private List<AbstractWaveFile> waveFiles1 = new ArrayList<AbstractWaveFile>();
    private List<AbstractWaveFile> waveFiles2 = new ArrayList<AbstractWaveFile>();
    private DualListModel<AbstractWaveFile> waveFilePickList = new DualListModel<AbstractWaveFile>(waveFileStation1,waveFiles1) ;
	private DualListModel<AbstractWaveFile> waveFilePickList1 = new DualListModel<AbstractWaveFile>(waveFileStation2,waveFiles2) ;
	private Map<String,FaultRecordAttachment> attachmentMap = new HashMap<>();
	private Map<String,AbstractWaveFile> waveFileMap = new HashMap<>();
	private boolean faultStatus = true;
	private boolean modelOperate = true;

	private String selectedText="";
	@PostConstruct
	public void init() {
		getOrCreateFrequentFaultsMap();
		queryFault = new FaultRecord();
		initAutoCompleteList();
		initTable();
		SystemParameter p = cacheM.get(ParamDesc.OMS_SERVICE_PUSH_EFFECTIVE_INTERVAL);
		if (p != null && NumberUtils.isParsable(p.getValue())) {
			long v = Long.parseLong(p.getValue());
			if (v != 0) {
				OMSInfo = "故障推送有效期为距故障时间" + v / 60000 + "分钟内。";
			}
		}
		openFrequentFaultAlarm();
		initFaultReason();
	}

	/**
	 * 疑似检修故障提示
	 */
	public void openFrequentFaultAlarm() {
		frequentFaults = findFrequentFaults();
		if (frequentFaults.size() > 0) {
			PrimeFaces.current().executeScript("PF('frequentFaultDialog').show()");
			deleteRecordFromApplicationMap();
		}
	}

	/**
	 * 初始化自动填充列表
	 */
	public void initAutoCompleteList() {
		etypeList = Arrays.asList("线路", "母线", "变压器", "发电机", "保护设备", "断路器", "其它");
		voltageList = Arrays.asList("35", "110", "220", "500", "750", "800", "1000");
		faultTypeList = Arrays.asList("瞬时性", "永久性", "单永", "单瞬", "两相接地", "两相相间", "三相短路", "其它");
		phases = Arrays.asList("A", "B", "C", "极一", "极二", "其他");
	}

	public void queryByTime() {
		if (queryDate1 == null) {
			queryDate1 = new Date(0);
		}
		if (queryDate2 == null) {
			queryDate2 = new Date();
		}
		initTable();
		refreshQueryParamter();
		selectFaults = null;
	}

	/**
	 * 重置按钮调用方法
	 */
	public void resetQuery() {
		queryDate1 = null;
		queryDate2 = null;
		queryFault.setFaultReson(null);;
		queryFault.setFaultType(null);
		resetqueryDate();
		isFault = "0"; // 是否故障查询
		selectedVoltage = "499";
		faultDevice = ""; // 故障设备
		queryByTime();
		selectFaults = null;
	}

	/**
	 * 是否故障单元格编辑 0 是故障， 1非故障
	 */
	public void editFaultStatus(FaultRecord selectEdit) {
		if (selectEdit != null) {
			selected = selectEdit;
			frm.saveFaultRecordOnly(selected);
			try {
				mpm.updateMaintenance(selectEdit);
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (selected.getStatus() == 1) {
				sourceManager.deleteFaultSourceInfo(selected);
			} else if (selected.getStatus() == 0) {
				sourceManager.saveFaultSourceUploadInfo(selected);
			}
		}
		selectFaults = null;
		addSuccessMessage("修改成功!");
	}

	/**
	 * 频繁故障提示--批量置为非故障
	 * 0 是故障， 1非故障
	 */
	public void frequentFaultBatchSetToNoFault() {
		if (selectFrequentFaults != null) {
			for (FaultRecord record : selectFrequentFaults) {
				// 如果是故障，则置为非故障
				if (record.getStatus() == 0) {
					record.setStatus(1);
					frm.saveFaultRecordOnly(record);
					// 当故障标记为非故障时要调用此方法删除相应的数据源统计信息
					sourceManager.deleteFaultSourceInfo(record);
				}
			}
			frequentFaults = findFrequentFaults();
			queryByTime();
			addSuccessMessage("修改成功！");
		} else {
			addErrorMessage("请选择故障记录！");
		}
	}

	/**
	 * 频繁故障提示--批量置为故障
	 * 0 是故障， 1非故障
	 */
	public void frequentFaultBatchSetToFault() {
		if (selectFrequentFaults != null) {
			List<FaultRecord> temp = new ArrayList<>();
			for (FaultRecord record : selectFrequentFaults) {
				frequentFaultsMap.put(record.getId(), new Date());
				temp.add(record);
			}
			frequentFaults.removeAll(temp);
		} else {
			addErrorMessage("请选择故障记录！");
		}
	}

	
	private void initFaultReason() {
		List<String> faultReasons = fm.findFaultAllReasons();
        for(String r : faultReasons){
                String key = PingYinUtil.getPingYinHeader(r);
                List<String> ss = faultReasonMap.get(key);
                if (ss == null) {
                        ss = new ArrayList<>();
                        faultReasonMap.put(key, ss);
                }
                ss.add(r);
        }
	}
	
	public List<String> complateFaultReason(String query){
        List<String> results = new ArrayList<String>();
        List<String> sets = new ArrayList<String>();
        for (String s : faultReasonMap.keySet()){
                if(s.startsWith(query))
                        sets.addAll(faultReasonMap.get(s));
        }
        results.addAll(sets);
        return results;
}
	
	/**
	 * 批量置为故障
	 * 0是故障， 1非故障
	 */
	public void batchSetToFault() {
		if (selectFaults != null) {
			for (FaultRecord record : selectFaults) {
				// 如果是非故障，则置为故障
				if (record.getStatus() == 1) {
					record.setStatus(0);
					frm.saveFaultRecordOnly(record);
					// 生产本次故障源信息，录波，报文
					sourceManager.saveFaultSourceUploadInfo(record);
				}
			}
			queryByTime();
			addSuccessMessage("修改成功！");
		} else {
			addErrorMessage("请选择故障记录！");
		}
	}

	/**
	 * 批量置为非故障 0 是故障， 1非故障
	 */
	public void batchSetToNoFault() {
		if (selectFaults != null) {
			for (FaultRecord record : selectFaults) {
				// 如果是故障，则置为非故障
				if (record.getStatus() == 0) {
					record.setStatus(1);
					frm.saveFaultRecordOnly(record);
					// 当故障标记为非故障时要调用此方法删除相应的数据源统计信息
					sourceManager.deleteFaultSourceInfo(record);
				}
			}
			queryByTime();
			addSuccessMessage("修改成功！");
		} else {
			addErrorMessage("请选择故障记录！");
		}
	}

	public void onDateSelectStart(SelectEvent popup1) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		facesContext.addMessage(null,
				new FacesMessage(FacesMessage.SEVERITY_INFO, "Date Selected", format.format(popup1.getObject())));
	}

	public void onDateSelectEnd(SelectEvent popup2) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		facesContext.addMessage(null,
				new FacesMessage(FacesMessage.SEVERITY_INFO, "Date Selected", format.format(popup2.getObject())));
	}

	/**
	 * 设置相别
	 */
	public void setupFaultPhase() {
		StringBuilder phaseBuilder = new StringBuilder();
		for (int i = 0; i < selectedPhase.length; i++) {
			phaseBuilder.append(selectedPhase[i]);
		}
		selected.setFaultPhase(phaseBuilder.toString());
	}

	// 打开选择设备模态框
	public void getEquipmentByStation() {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put("resizable", true);
		options.put("draggable", true);
		options.put("modal", true);
		options.put("width", 600);
		options.put("height", 400);
		Map<String, List<String>> params = new HashMap<>();
		params.put("chooseStation", Arrays.asList("false"));
		PrimeFaces.current().dialog().openDynamic("/ui/common/equipment_selector_single",  options,params);
	}

	/**
	 * 故障设备选择
	 */
	public void onFaultDeviceChosen(SelectEvent event) {
		IdentifiedObject equipment = (IdentifiedObject) event.getObject();
		faultDevice = equipment.getName();
	}

	/**
	 * 设备选择器选择后，填补数据
	 */
	public void onAnologSelectorChosen(SelectEvent event) {// 匹配id
		equipment = (IdentifiedObject) event.getObject();
		// 清除selected中的数据。避免多次选择设备后上一次的数据没有清空。
		selected.setStationId2(null);
		selected.setStationName2(null);
		showStation2 = false;
		if (equipment instanceof LineSegment) {
			LineSegment w = (LineSegment) equipment;
			selected.setEtype("线路");
			selected.setVoltage((int) w.getStandVoltagelevel());
			selected.setStationName(w.getStartStName());
			selected.setStationName2(w.getEndStName());
			selected.setStationId(w.getStartST());
			selected.setStationId2(w.getEndST());
			// 通过故障设备id查找Ledger，获得rank属性
			PrimaryEquipmentLedger ledger = equipmentLedgerM.getEquipmentLedgerByEquipmentId(w.getId());
			if (null != ledger) {
				selected.setRank(ledger.getPrimaryEquipmentScope());
				dispatchUnit = ledger.getDispatchUnit();
			}
			showStation2 = true;
		} else {
			SubstationLedger stationLedger = null;
			if (equipment instanceof BusbarSection) {
				BusbarSection w = (BusbarSection) equipment;
				selected.setEtype("母线");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof PowerTransformer) {
				PowerTransformer w = (PowerTransformer) equipment;
				selected.setEtype("变压器");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof GeneratingUnit) {
				GeneratingUnit w = (GeneratingUnit) equipment;
				selected.setEtype("发电机");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof HydroGeneratingUnit) {
				HydroGeneratingUnit w = (HydroGeneratingUnit) equipment;
				selected.setEtype("水力发电机");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof ThermalGeneratingUnit) {
				ThermalGeneratingUnit w = (ThermalGeneratingUnit) equipment;
				selected.setEtype("火力发电机");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof ProtectionEquipment) {
				// TODO 二次设备的ledger还未做
				ProtectionEquipment w = (ProtectionEquipment) equipment;
				selected.setEtype("保护设备");
				selected.setVoltage(w.getStandvoltage());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof Breaker) {
				Breaker w = (Breaker) equipment;
				selected.setEtype("断路器");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else if (equipment instanceof Compensator) {
				Compensator w = (Compensator) equipment;
				selected.setEtype("补偿器");
				selected.setVoltage((int) w.getStandVoltagelevel());
				selected.setStationName(w.getSubName());
				selected.setStationId(w.getSubId());
				stationLedger = stationLedgerM.findSubstationLedger(w.getSubId());
			} else {
				addErrorMessage("请选择正确的设备！");
				return;
			}
			if (null != stationLedger) {
				selected.setRank(stationLedger.getPrimaryEquipmentScope());
				dispatchUnit = stationLedger.getDispatchUnit();
			}
		}
		if (equipment != null) {
			// 直流线路用别称当做设备名称
			if (equipment instanceof DcLinesegment) {
				DcLinesegment w = (DcLinesegment) equipment;
				selected.setEquipment(w.getAliasName());
			} else {
				selected.setEquipment(equipment.getName());
			}
			selected.setEquipment_id(equipment.getId());
		}
		if (equipment instanceof ACLineSegment) { // 交流线路设置相别
			phases = Arrays.asList("A", "B", "C");
		} else if (equipment instanceof DcLinesegment) {
			phases = Arrays.asList("极一", "极二", "其他");
		} else {
			phases = Arrays.asList("A", "B", "C", "极一", "极二", "其他");
		}
		selected.setFaultPhase("");
		selected.setFaultType("");
		sameFaultTip();
	}

	/**
	 * 设备类型自动填充
	 */
	public List<String> completeEtype(String query) {
		List<String> results = new ArrayList<String>();
		for (String s : etypeList) {
			if (s.contains(query)) {
				results.add(s);
			}
		}
		return results;
	}

	/**
	 * 电压等级自动填充
	 */
	public List<String> completeVoltage(String query) {
		List<String> results = new ArrayList<String>();
		for (String s : voltageList) {
			if (s.contains(query)) {
				results.add(s);
			}
		}
		return results;
	}

	/**
	 * 故障类型选择按照相别进行区分 交流线路 单瞬、单永、两项接地、两项相间、三项断路 直流线路或其他 瞬时性、永久性、其他
	 */
	public List<String> completeFaultTypeList(String query) {
		List<String> results = new ArrayList<String>();
		String p = selected.getFaultPhase();
		if (null != equipment) {
			if (equipment instanceof ACLineSegment) {
				exchangeAclineFaultTypes(p);
			} else {
				exchangeDclineAndOtherFaultTypes();
			}
		} else {
			if ("线路".equals(selected.getEtype())) {
				if (null != selected.getEquipment() && selected.getEquipment().contains("直流"))
					exchangeDclineAndOtherFaultTypes();
				else
					exchangeAclineFaultTypes(p);
			} else if (StringUtils.isNotEmpty(selected.getEtype())) {
				exchangeDclineAndOtherFaultTypes();
			} else {
				exchangeAllFaultTypes();
			}
		}

		for (String s : faultTypeList) {
			if (s.contains(query))
				results.add(s);
		}
		return results;
	}

	public String getStatusText(Integer s) {
		String str = "";
		if (s != null) {
			if (s == 1) {
				str = "非故障";
			} else if (s == 0) {
				str = "故障";
			}
		}
		return str;
	}

	public String getPushText(Integer s) {
		String str = "";
		if (s != null) {
			if (s == 0) {
				str = "推送";
			} else if (s == 1) {
				str = "不推送";
			}
		}
		return str;
	}

	public void preCreateFault() {
		ifClick = false;
		selectedPhase = new String[0];
		selected = new FaultRecord();
		selected.setId(ObjectId.get().toString());
		create = true;
		hasRemark = false;
		equipment = null;
		dispatchUnit = null;
		modelOperate = false;
	}

	/**
	 * 编辑前判断--判断该故障是否正在被编辑
	 */
	public void preEditFault() {
		ifClick = false;
		modelOperate = true;
		selected = selectFaults.get(0);
		if (!checkEditPageIsUsed(selected.getId())) {
			addErrorMessage("该故障正在被编辑，请等待！");
			return;
		} else {
			create = false;
			// 由于时间选择后可能会造成展示的时间和编辑的时间不一致，故重新查一遍
			selected = fm.findById(selected.getId());
			// 获取调度单位
			if (null != selected.getEtype()) {
				if ("线路".equals(selected.getEtype())) {
					getEquipmengLedger("线路", selected.getEquipment_id());
				} else {
					getEquipmengLedger("变电站", selected.getStationId());
				}
				if (null != ledger) {
					dispatchUnit = ledger.getDispatchUnit();
				}
			}
			currentSelectRecordDesc = selected.getDescription();
			if (null != selected.getFaultPhase()) {
				char[] chars = selected.getFaultPhase().toCharArray();
				selectedPhase = new String[chars.length];
				for (int i = 0; i < chars.length; i++) {
					char c = chars[i];
					if (c == 'A' || c == 'B' || c == 'C') {
						selectedPhase[i] = String.valueOf(chars[i]);
					} else {
						selectedPhase[i] = String.valueOf(String.valueOf(chars[i]) + String.valueOf(chars[++i]));
					}
				}
			}
			// 根据故障设备类型设置故障的相别
			if (null != selected.getEtype() && selected.getEtype().equals("线路")) {
				LineSegment line = cim.getLineSegmentById(selected.getEquipment_id());
				if (line instanceof ACLineSegment) {
					phases = Arrays.asList("A", "B", "C");
				} else if (line instanceof DcLinesegment) {
					phases = Arrays.asList("极一", "极二", "其他");
				} else {
					phases = Arrays.asList("A", "B", "C", "极一", "极二", "其他");
				}
			} else {
				phases = Arrays.asList("A", "B", "C", "极一", "极二", "其他");
			}
			hasRemark = StringUtils.isNotEmpty(selected.getRemark());
			preChangeFaultTime();
			equipment = null;
			PrimeFaces.current().executeScript("PF('createFaultDialog').show()");
		}
	}

	/**
	 * 故障保存
	 */
	public void saveFault() {
		ifClick = false;
		if (!validateFault()) {
			return;
		}
		boolean matchedEqu = true;
		if (StringUtils.isEmpty(selected.getFaultPhase()) && selected.getEtype().equals("线路")) {
			addErrorMessage("故障相别为必填项!");
			return;
		} else if (StringUtils.isEmpty(selected.getEquipment_id())) {
			// 如果判定为手动输入系统需要将数据补充完整
			matchedEqu = replenishFaultInfo();
			// 如果系统为找到指定设备，则给出提示是否继续保存。
			if (!matchedEqu) {
				PrimeFaces.current().executeScript("PF('noticeDialog').show()");
				return;
			}
		}
		save();
		selectedPhase = new String[0];
		queryByTime();
		PrimeFaces.current().executeScript("PF('createFaultDialog').hide()");
		selected = null;
		selectFaults = null;
		addSuccessMessage("保存成功！");
	}

	/**
	 * 增量训练
	 */
	public void incrementModel() {
		boolean flag = true ;
		if(selected.getSource()==null||selected.getSource()!=1&&selected.getSource()!=2) {
			addErrorMessage("请确认故障来源为集中录波或保护录波！");
			return;
		}
		if(selected.getFaultReson()==null) {
			addErrorMessage("增量训练失败，实际原因不能为空！");
			return;
		}
		List<LibSvmData> incrementDatas = new ArrayList<>();
		selected = setFaultRecordLonAndLat(selected);
		AnalLinefaultEtl ale = fim.findAnalLinefaultEtlByFaultRecordId(selected.getId());
		if(ale==null) {
			ale =  fcm.faultIdentify(selected.getId(), selected.getEquipment_id(), selected.getFaultTime(),
					selected.getLon() == null ? 0 : selected.getLon().doubleValue(),
					selected.getLat() == null ? 0 : selected.getLat().doubleValue(), 1);
		}
		if(ale!=null) {
			LibSvmData data = fcm._getLibSvmDate(ale);
			incrementDatas.add(data);
			flag = fim.incrementTraining(incrementDatas, selected.getFaultReson(),pros.getFaultReasonIdentifyPath());
		}else {
			addErrorMessage("增量训练失败！");
			return;
		}
		if(!flag) {
			addErrorMessage("该类原因的模型不存在，请训练后添加！");
		}else {
			addSuccessMessage("增量训练成功！");;
		}
	}


	/**
	 * 当手动输入故障档案无匹配项时继续保存此故障。
	 */
	public void continueSaveFault() {
		save();
		selectedPhase = new String[0];
		queryByTime();
		PrimeFaces.current().executeScript("PF('noticeDialog').hide()");
		PrimeFaces.current().executeScript("PF('createFaultDialog').hide()");
		addSuccessMessage("保存成功！");
	}

	public void initDispatchUnit() {
		dispatchUnit = ledger.getDispatchUnit();
	}

	/**
	 * 删除故障
	 */
	public void deleteFault() {
		for (FaultRecord f : selectFaults) {
			frm.deleteFaultRecord(f.getId());
			try {
				//删除故障的时候需要重新计算设备特维相关信息
				mpm.updateMaintenance(f);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		selectFaults = null;
		initTable();
		addSuccessMessage("删除成功！");
	}

	public class DirNode {
		public String id;
		public String name;

		@Override
		public String toString() {
			return name;
		}

		public DirNode(String id, String name) {
			this.id = id;
			this.name = name;
		}
	}

	public void exportFaultDetail() {
		Object[] ps = getQueryParamter();
		List<FaultRecord> lineFaultList = fm.findFaultByRange(faultDevice, (Integer) ps[0], (Integer) ps[1],
				(Date) ps[2], (Date) ps[3], null);
		List<FaultRecordDetailDTO> faultRecordDetailDTOList = exportm
				.genFaultRecordDetailDTOBeforeExport(lineFaultList);
		exportm.exportExcel(faultRecordDetailDTOList);
		String exportDir = webpros.getExportTempPath();
		String fileName = "FaultRecord.xlsx";
		InputStream stream;
		try {
			stream = new FileInputStream(new File(exportDir + fileName));
			file = new DefaultStreamedContent(stream, exportDir, fileName);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 打开上传文件对话框
	 */
	public void chooseEquipment() {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put("resizable", true);
		options.put("draggable", true);
		options.put("modal", true);
		options.put("width", 650);
		options.put("height", 250);
		Map<String, List<String>> params = new HashMap<>();
		List<String> param = new ArrayList<>();
		param.add("1"); // 设置去除前几行
		params.put("ingnoreRows", param);
		openDialog("/ui/common/upload_excel_dialog", params, options);
	}

	/**
	 * 弹出故障详情对话框
	 *
	 * @param fault
	 */
	public void openFaultDialog(FaultRecord fault) {
		String path = "";
		if (StringUtils.isEmpty(fault.getEquipment_id())) {
			return;
		}
		String faultId = fault.getId();
		String targetPage = "";
		switch (fault.getEtype()) {
		case "线路": {
			if (StringUtils.isNotEmpty(fault.getEquipment_id())) {
				LineSegment line = cim.getLineSegmentById(fault.getEquipment_id());
				if(line==null) {
					LineSegmentHistory lineH =   cim.getHistoryLineSegmentById(fault.getEquipment_id());
					if (lineH instanceof ACLineSegmentHistory)
						targetPage = "acLineFaultReport.xhtml";
					else if (lineH instanceof DcLinesegmentHistory)
						targetPage = "dcLineFaultReport.xhtml";
				}else {
					if (line instanceof ACLineSegment)
						targetPage = "acLineFaultReport.xhtml";
					else if (line instanceof DcLinesegment)
						targetPage = "dcLineFaultReport.xhtml";
				}
			}else {
				targetPage = "acLineFaultReport.xhtml";
			}
			
			break;
		}
		case "母线":
			targetPage = "busFaultReport.xhtml";
			break;
		case "变压器":
			targetPage = "transfromerFaultReport.xhtml";
			break;
		default:
			break;
		}
		path = "/ui/dataview/devicefault/" + targetPage + "?faultId=" + faultId;
		PrimeFaces.current().executeScript("openFaultReport('" + path + "')");
	}


	/**
	 * 弹出故障详情对话框
	 *
	 * @param fault
	 */
	public void openFaultLogDialog(FaultRecord fault) {
		String path = "";
		if (StringUtils.isEmpty(fault.getEquipment_id())) {
			return;
		}
		String faultId = fault.getId();
		path = "/ui/dataview/devicefault/faultLogReport.xhtml?faultId=" + faultId;
		PrimeFaces.current().executeScript("openFaultLogReport('" + path + "')");
	}

	public void checkEditPageAct(FaultRecord f) {
		// TODO 用变电站id检查
		String faultId = f.getId();
		if (!checkEditPageIsUsed(faultId)) {
			addErrorMessage("该故障正在被【 " + gainOwner(faultId) + " 】编辑，请等待！");
		} else {
			openFaultDialog(f);
		}
	}

	/**
	 * 故障上传
	 */
	public void onSelectorChosen(SelectEvent event) {
		@SuppressWarnings("unchecked")
		List<List<String>> objs = (List<List<String>>) event.getObject();
		try {
			bx.generateFaultRecordByOmsExcelFile(objs);
		} catch (ParseException e) {
			addErrorMessage("故障时间格式不正确！请修改后上传");
		}
		// 更新列表
		initTable();
		addSuccessMessage("上传成功!");
	}

	public void selecteTypeItem(SelectEvent event) {
		String type = (String) event.getObject();
		if ("线路".equals(type)) {
			showStation2 = true;
		} else {
			showStation2 = false;
			selected.setStationId2(null);
			selected.setStationName2("");
		}
		phases = Arrays.asList("A", "B", "C", "极一", "极二", "其他");
	}

	public void onStartStationSelect(SelectEvent event) {
		String stationName = (String) event.getObject();
		Substation station = getStation(stationName);
		if (null != station) {
			selected.setStationId(station.getId());
		}
	}

	public void onEndStationSelect(SelectEvent event) {
		String stationName = (String) event.getObject();
		Substation station = getStation(stationName);
		if (null != station) {
			selected.setStationId2(station.getId());
		}
	}

	public void sameFaultTip() {
		if (selected.getFaultTime() != null && StringUtils.isNoneEmpty(selected.getEquipment_id())) {
			int timeInterval = 300;
			SystemParameter parameter = cacheM.get(ParamDesc.FAULT_JUDGE_TIME_INTERVAL);
			if (parameter != null && StringUtils.isNotEmpty(parameter.getValue())) {
				timeInterval = Integer.parseInt(parameter.getValue());
			}
			Calendar strat = Calendar.getInstance();
			strat.setTime(selected.getFaultTime());
			strat.add(Calendar.SECOND, -timeInterval);
			Date startTime = strat.getTime();
			Calendar end = Calendar.getInstance();
			end.setTime(selected.getFaultTime());
			end.add(Calendar.SECOND, timeInterval);
			Date endTime = end.getTime();
			samefaults = fm.findFaultByTimeDeviceId(startTime, endTime, selected.getEquipment_id());
			if (samefaults.size() > 0) {
				PrimeFaces.current().executeScript("PF('sameFauleDialog').show()");
			}
		}
	}

	public List<String> getHours() {
		List<String> hours = new ArrayList<String>();
		for (int i = 1; i < 24; i++) {
			hours.add(String.format("%02d", i));
		}
		return hours;
	}

	public List<String> getMinutesOrSeconds() {
		List<String> ms = new ArrayList<String>();
		for (int i = 1; i < 60; i++) {
			ms.add(String.format("%02d", i));
		}
		return ms;
	}

	public void onDateSelect(SelectEvent event) {
		onTimeChange();
	}

	public void onTimeChange() {
		String dateStr = DateUtil.getStringDate(faultDate, DateUtil.pattern_ymd);
		StringBuilder builder = new StringBuilder();
		builder.append(dateStr).append(" ").append(hour).append(":").append(minute).append(":").append(second);
		try {
			Date faultDate = DateUtil.getDateByString(builder.toString(), DateUtil.pattern_ymdhms);
			selected.setFaultTime(faultDate);
		} catch (Exception e) {
			selected.setFaultTime(null);
			addErrorMessage("选择时间错误！");
		}
	}

	public void preChangeFaultTime() {
		if (null == selected.getFaultTime()) {
			faultDate = new Date();
			return;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(selected.getFaultTime());
		faultDate = c.getTime();
		hour = String.format("%02d", c.get(Calendar.HOUR));
		minute = String.format("%02d", c.get(Calendar.MINUTE));
		second = String.format("%02d", c.get(Calendar.SECOND));
		// sameFaultTip();
	}

	/**
	 * 弹出设备管理单位维护对话框
	 *
	 * @return
	 */
	public String openEquipmentLedgerDialog() {
		String targetPage = "substationLedgerDialog.xhtml";
		String id = "";
		if (equipment instanceof LineSegment) {
			LineSegment w = (LineSegment) equipment;
			id = w.getId();
			targetPage = "lineSegmentLedgerDialog.xhtml";
		} else if (equipment instanceof BusbarSection) {
			BusbarSection w = (BusbarSection) equipment;
			id = w.getSubId();
		} else if (equipment instanceof PowerTransformer) {
			PowerTransformer w = (PowerTransformer) equipment;
			id = w.getSubId();
		} else if (equipment instanceof GeneratingUnit) {
			GeneratingUnit w = (GeneratingUnit) equipment;
			id = w.getSubId();
		} else if (equipment instanceof HydroGeneratingUnit) {
			HydroGeneratingUnit w = (HydroGeneratingUnit) equipment;
			id = w.getSubId();
		} else if (equipment instanceof ThermalGeneratingUnit) {
			ThermalGeneratingUnit w = (ThermalGeneratingUnit) equipment;
			id = w.getSubId();
		} else if (equipment instanceof ProtectionEquipment) {
			ProtectionEquipment w = (ProtectionEquipment) equipment;
			id = w.getSubId();
		} else if (equipment instanceof Breaker) {
			Breaker w = (Breaker) equipment;
			id = w.getSubId();
		} else if (equipment instanceof Compensator) {
			Compensator w = (Compensator) equipment;
			id = w.getSubId();
		}
		return "/ui/equipmentLedger/" + targetPage + "?id=" + id;
	}

	public void preEditLedger() {
		String id = "";
		if (StringUtils.isNotEmpty(selected.getEquipment())) {
			// 编辑
			if ("线路".equals(selected.getEtype())) {
				equipmentType = "线路";
				id = selected.getEquipment_id();
			} else {
				// 故障设备不是交直流线路时，找到设备所属的变电站的id
				equipmentType = "变电站";
				id = selected.getStationId();
			}
		} else {
			// 新建
			// 如果所选设备为线路，获得线路的id，否则，获得所选设备所属变电站的id
			if (null == equipment) {
				addErrorMessage("请先选择设备！");
				return;
			}
			if (equipment instanceof LineSegment) {
				LineSegment w = (LineSegment) equipment;
				id = w.getId();
				equipmentType = "线路";
			} else {
				if (equipment instanceof BusbarSection) {
					BusbarSection w = (BusbarSection) equipment;
					id = w.getSubId();
				} else if (equipment instanceof PowerTransformer) {
					PowerTransformer w = (PowerTransformer) equipment;
					id = w.getSubId();
				} else if (equipment instanceof GeneratingUnit) {
					GeneratingUnit w = (GeneratingUnit) equipment;
					id = w.getSubId();
				} else if (equipment instanceof HydroGeneratingUnit) {
					HydroGeneratingUnit w = (HydroGeneratingUnit) equipment;
					id = w.getSubId();
				} else if (equipment instanceof ThermalGeneratingUnit) {
					ThermalGeneratingUnit w = (ThermalGeneratingUnit) equipment;
					id = w.getSubId();
				} else if (equipment instanceof ProtectionEquipment) {
					ProtectionEquipment w = (ProtectionEquipment) equipment;
					id = w.getSubId();
				} else if (equipment instanceof Breaker) {
					Breaker w = (Breaker) equipment;
					id = w.getSubId();
				} else if (equipment instanceof Compensator) {
					Compensator w = (Compensator) equipment;
					id = w.getSubId();
				}
				equipmentType = "变电站";
			}
		}
		getEquipmengLedger(equipmentType, id);
	}

	/**
	 * 选择调度部门后，设置ledger的对应值
	 *
	 * @param event
	 */
	public void onDesorgDepartChosen(SelectEvent event) {
		ManagementUnitDict dept = (ManagementUnitDict) event.getObject();
		ledger.setDispatchUnit(dept.getName());
		ledger.setDispatchUnitId(dept.getId());
	}

	/**
	 * 选择运维部门后，设置ledger的对应值
	 *
	 * @param event
	 */
	public void onOpDepartChosen(SelectEvent event) {
		ManagementUnitDict dept = (ManagementUnitDict) event.getObject();
		ledger.setMaintenanceUnit(dept.getName());
		ledger.setMaintenanceUnitId(dept.getId());
		if (dept.getName().contains("超高压")) {
			ledger.setUnitType("超高压分局");
		} else if (dept.getName().contains("供电局")) {
			ledger.setUnitType("供电局");
		} else if (dept.getName().contains("电厂")) {
			ledger.setUnitType("发电厂");
		} else {
			ledger.setUnitType(null);
		}
	}

	/**
	 * 选择一次设备检修范围
	 *
	 * @param event
	 */
	public void onPrimaryScopeChosen(SelectEvent event) {
		ManagementUnitDict dept = (ManagementUnitDict) event.getObject();
		ledger.setPrimaryEquipmentScope(dept.getName());
	}

	/**
	 * 选择二次设备检修范围
	 *
	 * @param event
	 */
	public void onSecondryScopeChosen(SelectEvent event) {
		ManagementUnitDict dept = (ManagementUnitDict) event.getObject();
		ledger.setSecondaryEquipmentScope(dept.getName());
	}

	public String getWaveEquipmentType(Equipment e) {
		if (e instanceof WaveEquipment) {
			return "集中录波";
		} else if (e instanceof ProtectionEquipment) {
			return ((ProtectionEquipment) e).getType();
		}
		return "";
	}

	public boolean isAclineFault(FaultRecord fault) {
		if (fault != null && "线路".equals(fault.getEtype()) && fault.getEquipment_id() != null) {
			ACLineSegment line = cmc.getAclineid_map().get(fault.getEquipment_id());
			if (line != null)
				return true;
		}
		return false;
	}

	public void setFaultType(SelectEvent event) {
		// 该方法不可删除，用于向后台传递faultType
	}

	/**
	 * 新建时，自动生成故障过程
	 * 当故障过程有值时不可重复判断生成，无值时可重复点击调用该方法进行逻辑判断生成
	 */
	public void genFaultDescription() {
		if (StringUtils.isEmpty(selected.getDescription())) {
			if(selected.getEquipment()!=null&&!StringUtils.isEmpty(selected.getFaultPhase())&&selected.getFaultTime()!=null&&!StringUtils.isEmpty(selected.getFaultType())) {
				String description = fem.getFaultRecordprocessDesc(selected);
				selected.setDescription(description);
				ifClick = true;
			}else {
				ifClick = false;
				addErrorMessage("请完善故障信息");
			}
		}else {
			ifClick = true;
		}
	}

	/**
	 * 查看故障流程
	 */
	public void openFaultProcess(FaultRecord fault) {
		// 时间轴初始化
		processNodes = processM.findAllProcessNodesByFaultIds(fault.getId());
		for (ProcessNodeDTO p : processNodes) {
			String info = p.getHandlerLog().getLog();
			if (StringUtils.isNoneBlank(info)) {
				try {
					// 拆分info（目前info存的是json字符串，需要转化为json对象后，转化为各类dto显示）
					JSONObject jsStr = JSONObject.parseObject(info);
					// 直流线路信息
					JSONArray acLineInfoStr = jsStr.getJSONArray("acLineInfo");
					if (acLineInfoStr != null) {
						List<AcLineInfoDTO> acLineInfo = JSONObject.parseArray(acLineInfoStr.toJSONString(),
								AcLineInfoDTO.class);
						p.setAcLineInfos(acLineInfo);
					}
					// 刀闸信息
					JSONArray disconnectorInfoStr = jsStr.getJSONArray("disconnectorInfo");
					List<DisconnectorInfoDTO> disconnectorInfo = JSONObject
							.parseArray(disconnectorInfoStr.toJSONString(), DisconnectorInfoDTO.class);
					p.setDisconnectorInfos(disconnectorInfo);
					// 是否检修
					int conclusionStr = jsStr.getIntValue("conclusion");
					if (conclusionStr == 0) {
						p.setConclusion("未检修");
					} else if (conclusionStr == 1) {
						p.setConclusion("正在检修");
					} else {
						p.setConclusion("描述异常");
					}
					// E文件名称
					String efileName = jsStr.getString("efileName");
					p.setEfileName(efileName);
				} catch (Exception e) {
					log.info("json转化错误");
				}
			}
		}
		faultSources(fault);
	}

	public String getStateStr(String str) {
		if (StringUtils.isEmpty(str)) {
			return "";
		} else if (str.equals("false")) {
			return "X";
		} else {
			return "√";
		}
	}

	public String getCentralizedStr(String str) {
		if (StringUtils.isEmpty(str)) {
			return "";
		} else if (str.equals("false")) {
			return "X";
		} else {
			return "√";
		}
	}

	/**
	 * 合并故障时，加载故障附件和录波文件
	 */
	public void loadAttachmentAndWaveFiles() {
		initPickList();
		if(isSameFault()) {
			if(!"线路".equals(selectFaults.get(0).getEtype())) {
				addErrorMessage("工程师正在努力开发，目前仅支持线路故障合并功能！");
				return;
			}
			PrimeFaces.current().executeScript("PF('mergeFaultDialog').show()");
		}else {
			addErrorMessage("请选择同一条线路的故障进行合并");
		}
	}

	private void getAttachmentMap(List<FaultRecordAttachment> attachmentStation) {
		for (FaultRecordAttachment at : attachmentStation) {
			attachmentMap.put(at.getId(), at);
		}

	}

	private void initPickList() {
		selected = null;
		attachmentStation1.clear();
		attachmentStation2.clear();
		attachmentsPickList.getTarget().clear();
		attachmentsPickList.getSource().clear();
		attachmentsPickList1.getTarget().clear();
		attachmentsPickList1.getSource().clear();
		waveFilePickList.getTarget().clear();
		waveFilePickList.getSource().clear();
		waveFilePickList1.getTarget().clear();
		waveFilePickList1.getSource().clear();
		attachments1.clear();
		attachments2.clear();
		waveFileStation1.clear();
		waveFileStation2.clear();
		waveFiles1.clear();
		waveFiles2.clear();
	}

	/**
	 * 根据录波文件的path属性 截取字符形成name
	 * @param waveFiles3
	 * @return
	 */
	private List<AbstractWaveFile> setNameByPath(List<AbstractWaveFile> waveFiles) {
		for (AbstractWaveFile wave : waveFiles) {
			if(StringUtils.isNotBlank(wave.getPath())) {
				int index = wave.getPath().lastIndexOf("/");
				String name = wave.getPath().substring(index+1, wave.getPath().length());
				wave.setName(name);
				waveFileMap.put(name, wave);
			}
		}
		return waveFiles;
	}

	/**
	 * 保存合并故障--附件及录波文件
	 * 1.判断是否选择了故障，如果没有选择故障，提示未选择被合并的故障
	 * 2.如果选择了，把选择的附件和录波文件，保存在已选择的故障中
	 * 3.把附件保存在故障中
	 * 4.把录波文件保存在故障中
	 */
	public void saveMergeFault() {//TODO 根据target的id 从封装的map中将对应的文件对象取出放入选择的基准故障中并将文件对象和以前的故障关联解除
		if(selected != null) {
			//1.删除原有附件
			attManager.deleteByFaultId(selected.getId());
			//2.把附件保存在故障中
			attachmentStation1 = getAttachmentValueById(attachmentsPickList.getTarget());
			attachmentStation2 = getAttachmentValueById( attachmentsPickList1.getTarget());
			for(FaultRecordAttachment file:attachmentStation1) {
				if(file==null) {
					continue;
				}
				file.setFaultId(selected.getId());
				attManager.create(file);
			}
			for(FaultRecordAttachment file:attachmentStation2) {
				if(file==null) {
					continue;
				}
				file.setFaultId(selected.getId());
				attManager.create(file);
			}
			//3.删除原有录波文件
			waveFileMamager.deleteFaultWaveFileRelationByFaultId(selected.getId());
		     waveFiles1 = getWaveFileValueByName( waveFilePickList.getTarget());
		     waveFiles2 = getWaveFileValueByName( waveFilePickList1.getTarget());
			//4.把录波文件保存在故障中
			for(AbstractWaveFile waveFile:waveFiles1) {
				if(waveFile==null) {
					continue;
				}
				FaultWaveFileRelation relation =  new  FaultWaveFileRelation();
				relation.setFaultId(selected.getId());
				relation.setWaveFileId(waveFile.getId());
				if(waveFile instanceof WaveFile) {
					relation.setWaveFileType(WaveFileTypeEnum.WAVEFILE);
				}else if(waveFile instanceof ProtectWaveFile) {
					relation.setWaveFileType(WaveFileTypeEnum.PROTECT_WAVEFILE);
				}
				waveFileMamager.saveRelation(relation);
			}
			for(AbstractWaveFile waveFile:waveFiles2) {
				if(waveFile==null) {
					continue;
				}
				FaultWaveFileRelation relation =  new  FaultWaveFileRelation();
				relation.setFaultId(selected.getId());
				relation.setWaveFileId(waveFile.getId());
				if(waveFile instanceof WaveFile) {
					relation.setWaveFileType(WaveFileTypeEnum.WAVEFILE);
				}else if(waveFile instanceof ProtectWaveFile) {
					relation.setWaveFileType(WaveFileTypeEnum.PROTECT_WAVEFILE);
				}
				waveFileMamager.saveRelation(relation);
			}
			if(faultStatus) {//把未选择的故障记录置为非故障
				selectFaults.remove(selected);
				for (FaultRecord record : selectFaults) {
					if (record.getStatus() == 0) {
						record.setStatus(1);
						frm.saveFaultRecordOnly(record);
						sourceManager.deleteFaultSourceInfo(record);// 当故障标记为非故障时要调用此方法删除相应的数据源统计信息
					}
				}
			}
			addSuccessMessage("附件及录波文件合并成功");
		}else {
			addSuccessMessage("请选择目标故障");
		}
		selectFaults.clear();
	}

	/**
	 * 合并故障：根据所选基准故障更新picklist框
	 */
	public void onRowSelect(SelectEvent event) {
		initPickList();
		selected = (FaultRecord) event.getObject();//被选故障包含的录波和附件放入picklist右侧
		selectFaults.forEach((f)->{//遍历没被选择的故障，将其包含的附件和录波放入picklist左侧
			List<FaultRecordAttachment> attas = attManager.findByFaultId(f.getId());
			List<AbstractWaveFile> waves = waveFileMamager.listWaveFiles(f.getId());
			if(f.getId().equals(selected.getId())) {//处理被选故障包含的附件和录波
				for(FaultRecordAttachment fa:attas) {
					if(fa.getStationId().equals(selected.getStationId())) {
						attachments1.add(fa);
					}else if(fa.getStationId().equals(selected.getStationId2())) {
						attachments2.add(fa);
					}
				}
				for(AbstractWaveFile fa:waves) {
					Substation s = cim.getSubstationByName(fa.getStationName(), cmc.getS500List());//先判断500
					if(s==null) {
						s = cim.getSubstationByName(fa.getStationName(), cmc.getStationid_map().values());
						if(s==null) {
							continue;
						}
					}
					if(s.getId().equals(selected.getStationId())) {
						waveFiles1.add(fa);
					}else if(s.getId().equals(selected.getStationId2())) {
						waveFiles2.add(fa);
					}
				}
			}else {
				for(FaultRecordAttachment fa:attas) {
					if(fa.getStationId().equals(f.getStationId())) {
						attachmentStation1.add(fa);
					}else if(fa.getStationId().equals(f.getStationId2())) {
						attachmentStation2.add(fa);
					}
				}
				for(AbstractWaveFile fa:waves) {
					Substation s = cim.getSubstationByName(fa.getStationName(), cmc.getS500List());//先判断500
					if(s==null) {
						s = cim.getSubstationByName(fa.getStationName(), cmc.getStationid_map().values());
						if(s==null) {
							continue;
						}
					}
					if(s.getId().equals(f.getStationId())) {
						waveFileStation1.add(fa);
					}else if(s.getId().equals(f.getStationId2())) {
						waveFileStation2.add(fa);
					}
				}
			}
		});
		if(attachmentStation1.size()>0  || waveFileStation1.size()>0||attachmentStation2.size()>0||waveFileStation2.size()>0) {
			initAttachmentMapAndResetWaveFileName();
			attachmentsPickList = new DualListModel<FaultRecordAttachment>(attachmentStation1, attachments1);
			attachmentsPickList1 = new DualListModel<FaultRecordAttachment>(attachmentStation2,attachments2);
			waveFilePickList = new DualListModel<AbstractWaveFile>(waveFileStation1,waveFiles1) ;
			waveFilePickList1 = new DualListModel<AbstractWaveFile>(waveFileStation2,waveFiles2);
		}else {
			addErrorMessage("该故障无附件和录波文件");
		}
	}


	private void initAttachmentMapAndResetWaveFileName() {
		getAttachmentMap(attachmentStation1);
		getAttachmentMap(attachmentStation2);
		getAttachmentMap(attachments1);
		getAttachmentMap(attachments2);
		setNameByPath(waveFileStation1);
		setNameByPath(waveFileStation2);
		setNameByPath(waveFiles1);
		setNameByPath(waveFiles2);
	}

	/**
	 *  从map中根据id获得AbstractWaveFile对象
	 * @param waveFiles
	 * @return
	 */
	private List<AbstractWaveFile> getWaveFileValueByName(List<AbstractWaveFile> waveFiles) {
		List<AbstractWaveFile> waveFileList = new ArrayList<>();
		String[] nameArr = 	waveFiles.toString().split(",");
	    for (String name : nameArr) {
	    	name= StringUtils.strip(name,"[]").trim();
	    	waveFileList.add(waveFileMap.get(name));
		}
		return waveFileList;
	}

	/**
	 * 从map中根据id获得FaultRecordAttachment对象
	 * @param attachments
	 * @return
	 */
	private List<FaultRecordAttachment> getAttachmentValueById(List<FaultRecordAttachment> attachments) {
		List<FaultRecordAttachment> attachmentsList = new ArrayList<>();
		String[] idArr = attachments.toString().split(",");
	    for (String id : idArr) {
	    	id= StringUtils.strip(id,"[]").trim();
	    	attachmentsList.add(attachmentMap.get(id));
		}
		return attachmentsList;
	}
	/**
	 * 改变故障状态/ false:不做任何处理   true：将未选择的那一条故障记录置为非故障
	 */
	public void changeFaultStatus() {//TODO
		if(faultStatus) {
			faultStatus=false;
		}else {
			faultStatus=true;
		}
	}


	/**
	 *  合并故障时 ，判断故障设备id是否一致
	 */
	private boolean isSameFault() {
		String lastEquipmentId = selectFaults.get(0).getEquipment_id();
		for(FaultRecord select: selectFaults) {
			if(select.getEquipment_id().equals(lastEquipmentId)) {
				lastEquipmentId = select.getEquipment_id();
			}else {
				return false;
			}
		}
		return true;
	}


	/**
	 * 懒加载查询故障档案记录
	 */
	private void initTable() {
		lineFaultsModel = new LazyDataModel<FaultRecord>() {
			private static final long serialVersionUID = 2767501595145995278L;

			@Override
			public List<FaultRecord> load(int first, int pageSize, String sortField, SortOrder sortOrder,
					Map<String, Object> filters) {
				Object[] ps = getQueryParamter();
				try {
					if (getCurrentUser() != null) {
						lineFaults = rpf.findFaultByRange(getCurrentUser().getCode(), faultDevice, (Integer) ps[0],
								(Integer) ps[1], (Date) ps[2], (Date) ps[3], new int[] { first, first + pageSize },
								(String) ps[4], (String) ps[5]);
					}
				} catch (AuthorizationException e) {
					e.printStackTrace();
				}
				return lineFaults;
			}

			@Override
			public FaultRecord getRowData(String rowKey) {
				for (FaultRecord t : lineFaults) {
					if (t.getId().equals(rowKey)) {
						return t;
					}
				}
				return null;
			}

			@Override
			public Object getRowKey(FaultRecord object) {
				for (FaultRecord t : lineFaults) {
					if (t.getId().equals(object.getId())) {
						return t;
					}
				}
				return null;
			}
		};
		Object[] ps = getQueryParamter();
		try {
			if (getCurrentUser() != null) {
				count = rpf.countFault(getCurrentUser().getCode(), faultDevice, (Integer) ps[0], (Integer) ps[1],
						(Date) ps[2], (Date) ps[3], (String) ps[4], (String) ps[5]);
			}
		} catch (AuthorizationException e) {
			e.printStackTrace();
		}
		lineFaultsModel.setRowCount(count);
	}

	private void getOrCreateFrequentFaultsMap() {
		Map<String, Object> applictionMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap();
		if (applictionMap.containsKey(FAULTFREQUENTMAPKEY)) {
			frequentFaultsMap = (Map<String, Object>) applictionMap.get(FAULTFREQUENTMAPKEY);
		} else {
			frequentFaultsMap = new HashMap<String, Object>();
			applictionMap.put(FAULTFREQUENTMAPKEY, frequentFaultsMap);
		}
	}

	/**
	 * 删除ApplicationMap中，24小时之前的数据
	 */
	private void deleteRecordFromApplicationMap() {
		for (String key : frequentFaultsMap.keySet()) {
			if (frequentFaultsMap.get(key) instanceof Date) {
				Date timeDate = (Date) frequentFaultsMap.get(key);
				if ((new Date().getTime() - timeDate.getTime()) / (1000 * 3600 * 24) > 1) {
					frequentFaultsMap.remove(key);
				}
			}
		}
	}

	private Object[] getQueryParamter() {
		String s1 = DateUtil.getStringDate(queryDate1, DateUtil.pattern_ymd) + " 00:00:00";
		String s2 = DateUtil.getStringDate(queryDate2, DateUtil.pattern_ymd) + " 23:59:59";
		Date s = DateUtil.getDateByString(s1, DateUtil.pattern_ymdhms);
		Date e = DateUtil.getDateByString(s2, DateUtil.pattern_ymdhms);
		Integer voltage = null;
		if (NumberUtils.isParsable(selectedVoltage)) {
			voltage = Integer.parseInt(selectedVoltage);
		}
		Integer status = null;
		if (NumberUtils.isParsable(isFault)) {
			status = Integer.parseInt(isFault);
		}
		String faultType = null;
		String faultReason = null;
		if (queryFault != null) {
			faultReason = StringUtils.isNotEmpty(queryFault.getFaultReson()) ? queryFault.getFaultReson() : null;
			faultType = StringUtils.isNotEmpty(queryFault.getFaultType()) ? queryFault.getFaultType() : null;
		}
		return new Object[] { status, voltage, s, e, faultReason, faultType };
	}

	private void exchangeAclineFaultTypes(String p) {
		if (StringUtils.isEmpty(p)) {
			faultTypeList = Arrays.asList("单永", "单瞬", "两相接地", "两相相间", "三相短路");
			return;
		}

		if (p.length() == 1) {
			faultTypeList = Arrays.asList("单永", "单瞬");
		} else if (p.length() == 2) {
			faultTypeList = Arrays.asList("两相接地", "两相相间");
		} else if (p.length() == 3) {
			faultTypeList = Arrays.asList("三相短路", "其他");
		} else {
			faultTypeList = Arrays.asList("单永", "单瞬", "两相接地", "两相相间", "三相短路");
		}
	}

	private void exchangeDclineAndOtherFaultTypes() {
		faultTypeList = Arrays.asList("瞬时性", "永久性", "其他");
	}

	private void exchangeAllFaultTypes() {
		faultTypeList = Arrays.asList("单永", "单瞬", "两相接地", "两相相间", "三相短路", "瞬时性", "永久性", "其他");

	}

	/**
	 * 抽取起始杆塔
	 */
	private String getStartPoleByRemark(String remark) {
		if (StringUtils.isEmpty(remark)) {
			return null;
		}
		String reg = POLE_REGEX_1;
		Pattern p = Pattern.compile(reg);
		Matcher m = p.matcher(remark);
		if (m.matches()) {
			m.reset();
		} else {
			reg = POLE_REGEX_2;
			p = Pattern.compile(reg);
			m = p.matcher(remark);
		}
		String startPole = "";
		while (m.find()) {
			startPole = m.group(1);
			break;
		}
		return startPole;
	}

	/**
	 * 当判定为用户手动输入后补充故障信息
	 */
	private boolean replenishFaultInfo() {
		boolean b = false;
		if (StringUtils.isNotEmpty(selected.getStationId()) || StringUtils.isNotEmpty(selected.getStationId2())) {
			replenishStationId();
		}
		switch (selected.getEtype()) {
		case "线路":
			b = replenishLineFault();
			break;
		case "母线":
			b = replenishBusFault();
			break;
		case "变压器":
			b = replenishTransformerFault();
			break;
		case "发电机":
			b = replenishUnitFault();
			break;
		case "保护设备":
			b = replenishProtectionFault();
			break;
		case "断路器":
			b = replenishBreakerFault();
			break;
		case "其它":// 其他设备直接保存
			b = true;
			break;
		default:
			addErrorMessage("未找到对应的故障类型");
			break;
		}

		replenishRank();
		return b;
	}

	private void replenishStationId() {
		if (StringUtils.isEmpty(selected.getStationId())) {
			Substation station = getStation(selected.getStationName());
			if (null != station)
				selected.setStationId(station.getId());
		}
		if (StringUtils.isEmpty(selected.getStationId2()) && selected.getEtype().equals("线路")) {
			Substation station = getStation(selected.getStationName2());
			if (null != station)
				selected.setStationId2(station.getId());
		}
	}

	private void replenishRank() {
		if (null != selected.getEquipment_id()) {
			String rank = "";
			if (selected.getEtype().equals("线路")) {
				SubstationLedger stationLedger = stationLedgerM.findSubstationLedger(selected.getStationId());
				if (null != stationLedger) {
					rank = stationLedger.getPrimaryEquipmentScope();
				}
			} else {
				SubstationLedger stationLedger = stationLedgerM.findSubstationLedger(selected.getStationName());
				if (null != stationLedger) {
					rank = stationLedger.getPrimaryEquipmentScope();
				}
			}
			selected.setRank(rank);
		}
	}

	/**
	 * 完善线路故障信息
	 */
	private boolean replenishLineFault() {
		boolean b = false;
		for (Entry<String, ACLineSegment> entry : cmc.getAclineid_map().entrySet()) {
			if (entry.getValue().getName().equals(selected.getEquipment())) {
				selected.setEquipment_id(entry.getValue().getId());
				b = true;
				break;
			}
		}
		if (!b) {
			for (Entry<String, DcLinesegment> entry : cmc.getDclineid_map().entrySet()) {
				if (entry.getValue().getName().equals(selected.getEquipment())) {
					selected.setEquipment_id(entry.getValue().getId());
					b = true;
					break;
				}
			}
		}
		return b;
	}

	/**
	 * 完善母线故障信息
	 */
	private boolean replenishBusFault() {
		boolean b = false;
		List<BusbarSection> buses = cim.getBusbarSectionsByStationIdAndName(selected.getStationId(),
				selected.getEquipment());
		if (buses.size() > 0) {
			b = true;
			selected.setEquipment_id(buses.get(0).getId());
		}
		return b;
	}

	/**
	 * 完善变压器故障信息
	 */
	private boolean replenishTransformerFault() {
		boolean b = false;
		PowerTransformer transformer = cim.getPowerTransformersByStationIdAndPowerName(selected.getStationId(),
				selected.getEquipment());
		if (null != transformer) {
			b = true;
			selected.setEquipment_id(transformer.getId());
		}
		return b;
	}

	/**
	 * 完善断路器故障信息
	 */
	private boolean replenishBreakerFault() {
		boolean b = false;
		List<Breaker> breakers = cim.getBreakersByStationIdAndName(selected.getStationId(), selected.getEquipment());
		if (breakers.size() > 0) {
			b = true;
			selected.setEquipment_id(breakers.get(0).getId());
		}
		return b;
	}

	/**
	 * 完善发电机故障信息
	 */
	private boolean replenishUnitFault() {
		boolean b = false;
		List<Equipment> equipments = new ArrayList<Equipment>();
		equipments.addAll(cim.getGeneratingUnitsByStationIdAndName(selected.getStationId(), selected.getEquipment()));
		if (equipments.size() == 0) {
			equipments.addAll(
					cim.getThermalGeneratingUnitsByStationIdAndName(selected.getStationId(), selected.getEquipment()));
		} else if (equipments.size() == 0) {
			equipments.addAll(
					cim.getHydroGeneratingUnitsByStationIdAndName(selected.getStationId(), selected.getEquipment()));
		}
		if (equipments.size() > 0) {
			b = true;
			selected.setEquipment_id(equipments.get(0).getId());
		}
		return b;
	}

	/**
	 * 完善保护设备故障信息
	 */
	private boolean replenishProtectionFault() {
		boolean b = false;
		List<ProtectionEquipment> protections = cim.getProtectionByStationIdAndEid(selected.getStationId(),
				selected.getEquipment());
		if (protections.size() > 0) {
			selected.setEquipment_id(protections.get(0).getId());
			b = true;
		}
		return b;
	}

	private boolean validateFault() {
		boolean b = false;
		if (StringUtils.isEmpty(selected.getEquipment())) {
			addErrorMessage("故障设备为必填项！");
		} else if (StringUtils.isEmpty(selected.getEtype())) {
			addErrorMessage("故障类型为必填项！");
		} else if (StringUtils.isEmpty(selected.getStationName())) {
			addErrorMessage("变电站为必填项！");
		} else if (null == selected.getFaultTime()) {
			addErrorMessage("故障时间为必填项！");
		} else if (StringUtils.isEmpty(selected.getFaultPhase()) && selected.getEtype().equals("线路")) {
			addErrorMessage("故障相别为必填项!");
		} else {
			b = true;
		}
		return b;
	}

	private void save() {
		saveLedger();
		if (create) {
			selected.setSource(0);// 0标识是人工录入的
			selected.setStatus(0);
			if (StringUtils.isNotEmpty(selected.getDescription())) {
				selected.setDescStatus(1);
			}
		}
		if (!hasRemark) {
			try {
				String startPole = getStartPoleByRemark(selected.getRemark());
				if (StringUtils.isNotEmpty(startPole)) {
					selected.setStartPole(Integer.valueOf(startPole));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			if (create) {
				FaultRecordWrapper wrapper = new FaultRecordWrapper(false, false, selected);
				frm.saveFaultRecord(wrapper);
			} else {
				if (StringUtils.isNotEmpty(selected.getDescription())
						&& !selected.getDescription().equals(currentSelectRecordDesc)) {
					selected.setDescStatus(1);
				} else if (StringUtils.isEmpty(selected.getDescription())) {
					selected.setDescStatus(0);
				}
				frm.saveFaultRecordOnly(selected);
				//更新故障的时候需要重新计算设备特维相关信息,更新触发逻辑是编辑了故障时间或者相别导致和数据库数据不一致
				FaultRecord dbfr = fm.findById(selected.getId());
				if(dbfr.getFaultTime().getTime()!=selected.getFaultTime().getTime()
						|| StringUtils.isNotEmpty(dbfr.getFaultPhase()) && !dbfr.getFaultPhase().equals(selected.getFaultPhase())) {
					mpm.updateMaintenance(selected);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String gainOwner(String faultId) {
		// TODO 用变电站id检查
		String ownerId = lockM.gainOwenr(faultId);
		if ("管理员".equals(ownerId)) {
			return ownerId;
		} else {
			return personM.findPersonnelById(ownerId).getName();
		}
	}

	/**
	 * 检查故障档案是否正在被编辑
	 */
	private boolean checkEditPageIsUsed(String faultId) {
		// TODO 改为传变电站的id,锁该变电站
		return lockM.gainLock(faultId, new Date().getTime(), getCurrentUser().getId());
	}

	/**
	 * 通过变电站名称查找变电站
	 *
	 * @param stationName
	 */
	private Substation getStation(String stationName) {
		for (Entry<String, Substation> entry : cmc.getStationid_map().entrySet()) {
			if (entry.getValue().getName().equals(stationName)) {
				return entry.getValue();
			}
		}
		return null;
	}

	/**
	 * 根据applictionMap匹配查询24小时之内的故障
	 * @return
	 */
	private List<FaultRecord> findFrequentFaults() {
		List<FaultRecord> lastFaults = fm.findFrequentFaultBefore24Hours();
		List<FaultRecord> temp = new ArrayList<>();
		for (FaultRecord f : lastFaults) {
			if (frequentFaultsMap.containsKey(f.getId())) {
				temp.add(f);
			}
		}
		lastFaults.removeAll(temp);
		return lastFaults;
	}

	/**
	 * 故障源统计信息
	 */
	private void faultSources(FaultRecord fault) {
		// sourceInfos.clear();
		sourceInfos = faultSourcesM.getFaultUploadInfoDTOByFaultRecord(fault);
		// sourceInfos.add(faultSourcesInfo);
	}

	/**
	 * 保存ledger
	 */
	private void saveLedger() {
		if (null != ledger) {
			if ("线路".equals(equipmentType)) {
				PrimaryEquipmentLedger lineLedger = (PrimaryEquipmentLedger) ledger;
				lineLedgerM.createOrUpdatePrimaryEquipmentLedger(lineLedger);
			} else if ("变电站".equals(equipmentType)) {
				SubstationLedger stationLedger = (SubstationLedger) ledger;
				stationLedgerM.createOrUpdateSubstationLedger(stationLedger);
			}
		}
	}

	/**
	 * 根据故障设备类型、故障设备id找到对应的ledger
	 *
	 * @param equipmentType
	 * @param equipmentId
	 */
	private void getEquipmengLedger(String equipmentType, String equipmentId) {
		if ("线路".equals(equipmentType)) {
			PrimaryEquipmentLedger lineLedger = equipmentLedgerM.getEquipmentLedgerByEquipmentId(equipmentId);
			if (null != lineLedger) {
				ledger = lineLedger;
			} else {
				ledger = new PrimaryEquipmentLedger();
			}
		} else if ("变电站".equals(equipmentType)) {
			SubstationLedger stationLedger = stationLedgerM.findSubstationLedger(equipmentId);
			if (null != stationLedger) {
				ledger = stationLedger;
			} else {
				ledger = new SubstationLedger();
			}
		}
	}


	public void rePredict() {
		if(selected==null) {
			predictResult = "失败";
			addErrorMessage("所选数据为空");
			return;
		}
		if(selected.getSource()!=1&&selected.getSource()!=2) {
			predictResult = "失败";
			addErrorMessage("请确认故障来源为集中录波或保护录波！");
			return;
		}
		selected = setFaultRecordLonAndLat(selected);
		AnalLinefaultEtl ale = fim.findAnalLinefaultEtlByFaultRecordId(selected.getId());
		if(ale==null) {
			ale =  fcm.faultIdentify(selected.getId(), selected.getEquipment_id(), selected.getFaultTime(),
					selected.getLon() == null ? 0 : selected.getLon().doubleValue(),
					selected.getLat() == null ? 0 : selected.getLat().doubleValue(), 1);
		}
		if(ale!=null) {
			LibSvmData data = fcm._getLibSvmDate(ale);
			String predictReason =fim.getPredictReason(data,pros.getFaultReasonIdentifyPath());
			if(predictReason==null) {
				predictReason = "其他";
			}
			selected.setFaultForecastReson(predictReason);
			predictResult = "完成";
		}else {
			predictResult = "失败";
		}
	}

	/**
	 * 给FaultRecord设置经纬度信息
	 * @param fr
	 * @return
	 */
    private FaultRecord setFaultRecordLonAndLat(FaultRecord fr) {
    	List<FaultRecord> faults = new ArrayList<>();
		faults.add(fr);
		faults = frm.setupFaultLonAndLat(faults, true);
		fr = faults.get(0);
		return fr;
    }

	/**
	 * oms数据上传
	 */
	public void handleFileUpload(FileUploadEvent event) {
		UploadedFile uploadFile = event.getFile();
		String suffix = uploadFile.getFileName().substring(uploadFile.getFileName().lastIndexOf('.'));
		StringBuilder errorInfos = new StringBuilder();
		OmsExcelDataListener listener = new OmsExcelDataListener(errorInfos);
		if(suffix.equals(".xlsx")) {
			try {
				InputStream fis = uploadFile.getInputstream();
				EasyExcel.read(fis, ImportOmsDTO.class, listener).sheet().doRead();
				fis.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				addErrorMessage("文件读取失败");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		for (FaultDetail fd : listener.getFaultDetails()) {
			try {
				fdM.createOrUpdate(fd);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if(errorInfos != null && errorInfos.length()>0){
			errorInfos.append(" 以上数据请调整后重新进行上传");
			alertErrorMessage(errorInfos.toString());
		}

	}


	public FaultRecord getSelected() {
		return selected;
	}

	public void setSelected(FaultRecord selected) {
		this.selected = selected;
	}

	public LazyDataModel<FaultRecord> getLineFaultsModel() {
		return lineFaultsModel;
	}

	public void setLineFaultsModel(LazyDataModel<FaultRecord> lineFaultsModel) {
		this.lineFaultsModel = lineFaultsModel;
	}

	public String[] getSelectedPhase() {
		return selectedPhase;
	}

	public void setSelectedPhase(String[] selectedPhase) {
		this.selectedPhase = selectedPhase;
	}

	public String getTmpPath() {
		return tmpPath;
	}

	public void setTmpPath(String tmpPath) {
		this.tmpPath = tmpPath;
	}

	public StreamedContent getFile() {
		return file;
	}

	public void setFile(StreamedContent file) {
		this.file = file;
	}

	public List<AnalyseLogDTO> getAnalyseLogDTOs() {
		return analyseLogDTOs;
	}

	public void setAnalyseLogDTOs(List<AnalyseLogDTO> analyseLogDTOs) {
		this.analyseLogDTOs = analyseLogDTOs;
	}

	public String getIsFault() {
		return isFault;
	}

	public void setIsFault(String isFault) {
		this.isFault = isFault;
	}

	public String getSelectedVoltage() {
		return selectedVoltage;
	}

	public void setSelectedVoltage(String selectedVoltage) {
		this.selectedVoltage = selectedVoltage;
	}

	public String getFaultDevice() {
		return faultDevice;
	}

	public void setFaultDevice(String faultDevice) {
		this.faultDevice = faultDevice;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public List<String> getPhases() {
		return phases;
	}

	public void setPhases(List<String> phases) {
		this.phases = phases;
	}

	public FaultRecord getSelectEdit() {
		return selectEdit;
	}

	public void setSelectEdit(FaultRecord selectEdit) {
		this.selectEdit = selectEdit;
	}

	public boolean isShowStation2() {
		return showStation2;
	}

	public void setShowStation2(boolean showStation2) {
		this.showStation2 = showStation2;
	}

	public boolean isCreate() {
		return create;
	}

	public void setCreate(boolean create) {
		this.create = create;
	}

	public String getHour() {
		return hour;
	}

	public void setHour(String hour) {
		this.hour = hour;
	}

	public String getMinute() {
		return minute;
	}

	public void setMinute(String minute) {
		this.minute = minute;
	}

	public String getSecond() {
		return second;
	}

	public void setSecond(String second) {
		this.second = second;
	}

	public Date getFaultDate() {
		return faultDate;
	}

	public void setFaultDate(Date faultDate) {
		this.faultDate = faultDate;
	}

	public PowerResourceLedger getLedger() {
		return ledger;
	}

	public void setLedger(PowerResourceLedger ledger) {
		this.ledger = ledger;
	}

	public List<FaultRecord> getSamefaults() {
		return samefaults;
	}

	public void setSamefaults(List<FaultRecord> samefaults) {
		this.samefaults = samefaults;
	}

	public String getOMSInfo() {
		return OMSInfo;
	}

	public void setOMSInfo(String oMSInfo) {
		OMSInfo = oMSInfo;
	}

	public IdentifiedObject getEquipment() {
		return equipment;
	}

	public void setEquipment(IdentifiedObject equipment) {
		this.equipment = equipment;
	}

	public String getDispatchUnit() {
		return dispatchUnit;
	}

	public void setDispatchUnit(String dispatchUnit) {
		this.dispatchUnit = dispatchUnit;
	}

	public List<FaultRecord> getSelectFaults() {
		return selectFaults;
	}

	public void setSelectFaults(List<FaultRecord> selectFaults) {
		this.selectFaults = selectFaults;
	}

	public boolean isIfClick() {
		return ifClick;
	}

	public void setIfClick(boolean ifClick) {
		this.ifClick = ifClick;
	}

	public List<ProcessNodeDTO> getProcessNodes() {
		return processNodes;
	}

	public void setProcessNodes(List<ProcessNodeDTO> processNodes) {
		this.processNodes = processNodes;
	}

	public List<FaultUploadInfoDTO> getSourceInfos() {
		return sourceInfos;
	}

	public void setSourceInfos(List<FaultUploadInfoDTO> sourceInfos) {
		this.sourceInfos = sourceInfos;
	}

	public List<FaultRecord> getFrequentFaults() {
		return frequentFaults;
	}

	public void setFrequentFaults(List<FaultRecord> frequentFaults) {
		this.frequentFaults = frequentFaults;
	}

	public List<FaultRecord> getSelectFrequentFaults() {
		return selectFrequentFaults;
	}

	public void setSelectFrequentFaults(List<FaultRecord> selectFrequentFaults) {
		this.selectFrequentFaults = selectFrequentFaults;
	}

	public FaultRecord getQueryFault() {
		return queryFault;
	}

	public void setQueryFault(FaultRecord queryFault) {
		this.queryFault = queryFault;
	}


	public List<FaultRecordAttachment> getAttachments1() {
		return attachments1;
	}

	public void setAttachments1(List<FaultRecordAttachment> attachments1) {
		this.attachments1 = attachments1;
	}

	public List<FaultRecordAttachment> getAttachments2() {
		return attachments2;
	}

	public void setAttachments2(List<FaultRecordAttachment> attachments2) {
		this.attachments2 = attachments2;
	}

	public DualListModel<FaultRecordAttachment> getAttachmentsPickList() {
		return attachmentsPickList;
	}

	public void setAttachmentsPickList(DualListModel<FaultRecordAttachment> attachmentsPickList) {
		this.attachmentsPickList = attachmentsPickList;
	}

	public DualListModel<FaultRecordAttachment> getAttachmentsPickList1() {
		return attachmentsPickList1;
	}

	public void setAttachmentsPickList1(DualListModel<FaultRecordAttachment> attachmentsPickList1) {
		this.attachmentsPickList1 = attachmentsPickList1;
	}

	public List<AbstractWaveFile> getWaveFiles1() {
		return waveFiles1;
	}

	public void setWaveFiles1(List<AbstractWaveFile> waveFiles1) {
		this.waveFiles1 = waveFiles1;
	}

	public List<AbstractWaveFile> getWaveFiles2() {
		return waveFiles2;
	}

	public void setWaveFiles2(List<AbstractWaveFile> waveFiles2) {
		this.waveFiles2 = waveFiles2;
	}

	public DualListModel<AbstractWaveFile> getWaveFilePickList() {
		return waveFilePickList;
	}

	public void setWaveFilePickList(DualListModel<AbstractWaveFile> waveFilePickList) {
		this.waveFilePickList = waveFilePickList;
	}

	public DualListModel<AbstractWaveFile> getWaveFilePickList1() {
		return waveFilePickList1;
	}

	public void setWaveFilePickList1(DualListModel<AbstractWaveFile> waveFilePickList1) {
		this.waveFilePickList1 = waveFilePickList1;
	}

	public boolean isFaultStatus() {
		return faultStatus;
	}

	public void setFaultStatus(boolean faultStatus) {
		this.faultStatus = faultStatus;
	}

	public String getPredictResult() {
		return predictResult;
	}

	public void setPredictResult(String predictResult) {
		this.predictResult = predictResult;
	}

	public boolean isModelOperate() {
		return modelOperate;
	}

	public void setModelOperate(boolean modelOperate) {
		this.modelOperate = modelOperate;
	}

	public String getSelectedText() {
		return selectedText;
	}

	public void setSelectedText(String selectedText) {
		this.selectedText = selectedText;
	}

}
